﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.ObjectMapping;
using AutoMapper.QueryableExtensions;
using FwProject.Authorization.Users;
using FwProject.Core.SettlementInfoModel;
using FwProject.PrePaymentInfo.Dto;
using FwProject.Restaurant.Dto;
using X.PagedList;
using Abp.UI;
using FwProject.Restaurant;

namespace FwProject.PrePaymentInfo
{
    /// <summary>
    /// 收款管理
    /// </summary>

    [AbpAuthorize]
    public class ReceiptInfoAppService : FwProjectAppServiceBase, IReceiptInfoAppService
    {
        public readonly IRepository<ReceiptInfoModel, Guid> _repositoryReceiptInfo;
        public readonly IRepository<ReceiptInfoBySettlementModel, Guid> _repositoryReceiptInfoBySettlementModel;
        public readonly IRepository<SettlementInfo, Guid> _repositorySettlement;
        public readonly IRepository<User, long> _repositoryUser;
        public readonly IRepository<SettlementAccount, Guid> _repositorySettlementAccount;
        public readonly IPrePaymentInfoAppService _prePaymentInfoAppService;//预收款服务
        public readonly IRestaurantAppService _restaurantAppService;

        public readonly IRepository<PrePaymentInfoModel, Guid> _repositoryPrePaymentInfoModel;
        public IObjectMapper _map { get; set; }
        public IGuidGenerator _guid { get; set; }
        public ReceiptInfoAppService(IRepository<ReceiptInfoModel, Guid> repositoryReceiptInfo, IRepository<SettlementInfo, Guid> repositorySettlement,
            IRepository<User, long> repositoryUser, IRepository<SettlementAccount, Guid> repositorySettlementAccount,
            IRepository<ReceiptInfoBySettlementModel, Guid> repositoryReceiptInfoBySettlementModel,
             IPrePaymentInfoAppService prePaymentInfoAppService,
             IRestaurantAppService restaurantAppService,
             IRepository<PrePaymentInfoModel, Guid> repositoryPrePaymentInfoModel)
        {
            _repositoryReceiptInfoBySettlementModel = repositoryReceiptInfoBySettlementModel;
            _repositoryReceiptInfo = repositoryReceiptInfo;
            _repositorySettlement = repositorySettlement;
            _repositoryUser = repositoryUser;
            _repositorySettlementAccount = repositorySettlementAccount;
            _guid = SequentialGuidGenerator.Instance;
            _prePaymentInfoAppService = prePaymentInfoAppService;
            _restaurantAppService = restaurantAppService;
            _repositoryPrePaymentInfoModel = repositoryPrePaymentInfoModel;
        }
        /// <summary>
        /// 修改缴款状态
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task EditStatus(Guid id, Guid payMentId)
        {
            var user = await base.GetCurrentUserAsync();
            var model = await _repositoryReceiptInfo.GetAsync(id);
            model.PaymentState = PaymentState.已缴款;
            model.DateofPayment = DateTime.Now;
            model.PaymentPersonUserId = user.Id;
            model.PaymentPerson = user.Name;
            model.PaymentinfoId = payMentId;
            await _repositoryReceiptInfo.UpdateAsync(model);
        }
        /// <summary>
        /// 收款单保存
        /// </summary>
        /// <param name="id"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Update(Guid id, ReceiptInfoInput input)
        {
            ///实际情况
            var user = await _repositoryUser.GetAsync(input.AgentPeoperUserId);
            var model = _repositoryReceiptInfo.GetAllIncluding(o => o.RestaurantInfoModel).Where(o => o.Id == id).FirstOrDefault();

            var parCountPrice = await _prePaymentInfoAppService.GetRestaurantInfoByReceiptInfoIdPayment(model.RestaurantId, model.Id);
            if (input.UsePrePayment > parCountPrice)
                throw new UserFriendlyException("预付金不足");

            model.AgentPeoperUserId = input.AgentPeoperUserId;
            model.AgentPeoper = user.Name;
            model.Dateofreceipt = input.Dateofreceipt;
            model.RemarksConten = input.RemarksConten;
            model.UsePrePayment = input.UsePrePayment;
            model.UsePrePaymentSurplus = parCountPrice - input.UsePrePayment;
            model.TaskBackAmount = input.TaskBackAmount;
            model.PreferentialAmount = 0;
            model.ReceiptInfoStatus = input.ReceiptInfoStatus;
            model.ActualAmount = 0;
            ///得到所有的该缴款单的收据单重新生成数据
            var receiptModel = _repositoryReceiptInfoBySettlementModel.GetAll().Where(o => o.ReceiptInfoId == id && o.ToVoidStatus == ToVoidStatus.未作废).OrderBy(o => o.CreationTime);

            var SumTaskAmountByUsePrePrice = input.TaskBackAmount + input.UsePrePayment + input.PreferentialAmount;//总金额
                                                                                                                   // var PreferentialAmount = receiptModel.Sum(o=>o.PreferentialAmount);//优惠金额

            var PreferentialAmount = 0.0m;
            var UsePrePayment = input.UsePrePayment;//预收金额///计算出所有符合当前结算的收据     

            foreach (var item in receiptModel)
            {
                var i = _repositorySettlement.GetAll().Where(o => o.Id == item.SettlementId).FirstOrDefault();
                ///总金额如果大于应收

                ///得到该收据已经算过的账目
                var bySettlment = _repositoryReceiptInfoBySettlementModel.GetAll().Where(o => o.ReceiptInfoId != id && o.SettlementId == item.SettlementId && o.ToVoidStatus != ToVoidStatus.已作废).GroupBy(o => o.SettlementId).Select(o => new
                {
                    Id = o.Key,
                    TaskNotBackAmount = o.Sum(s => s.TaskNotBackAmount),
                    TaskBackAmount = o.Sum(s => s.TaskBackAmount),
                    UsePrePayment = o.Sum(s => s.UsePrePayment),
                    PreferentialAmount = o.Sum(s => s.PreferentialAmount),
                    SumAmount = o.Sum(s => (s.PreferentialAmount + s.UsePrePayment + s.TaskBackAmount))
                }).ToList()?.FirstOrDefault();
                if (bySettlment == null)
                {
                    bySettlment = new
                    {
                        Id = Guid.NewGuid(),
                        TaskNotBackAmount = 0.0m,
                        TaskBackAmount = 0.0m,
                        UsePrePayment = 0.0m,
                        PreferentialAmount = 0.0m,
                        SumAmount = 0.0m,
                    };
                }
                //总的未付款情况
                var TaskNotBackAmount = i.Actualprice - bySettlment.SumAmount;//剩余多少钱
                item.ActualAmount = TaskNotBackAmount;

                model.ActualAmount += TaskNotBackAmount;
                //gloagTaskNotBackAmount = TaskNotBackAmount - item.ActualAmount;

                item.UsePrePayment = 0;
                item.PreferentialAmount = 0;
                item.TaskBackAmount = 0;
                item.TaskNotBackAmount = 0;

                if (TaskNotBackAmount > 0)
                {
                    //优惠金额如果大于应收
                    if (PreferentialAmount >= TaskNotBackAmount)
                    {
                        i.ReceivedDiscount = item.ActualAmount + bySettlment.PreferentialAmount;
                        i.ReceivedPrice = bySettlment.TaskBackAmount;
                        i.UsePrePayment = bySettlment.UsePrePayment;
                        //使用后剩余优惠金额
                        PreferentialAmount = PreferentialAmount - TaskNotBackAmount;
                        item.UsePrePayment = 0;
                        item.PreferentialAmount = TaskNotBackAmount;
                        item.TaskBackAmount = 0;
                        item.TaskNotBackAmount = 0;


                    }
                    else if (UsePrePayment >= TaskNotBackAmount)
                    {
                        ///一次性使用预收金额
                        i.UsePrePayment = item.ActualAmount + bySettlment.UsePrePayment;
                        i.ReceivedDiscount = bySettlment.PreferentialAmount;
                        i.ReceivedPrice = bySettlment.TaskBackAmount;

                        UsePrePayment = UsePrePayment - TaskNotBackAmount;


                        item.UsePrePayment = TaskNotBackAmount;
                        item.PreferentialAmount = 0;
                        item.TaskBackAmount = 0;
                        item.TaskNotBackAmount = 0;

                    }
                    else if (UsePrePayment + PreferentialAmount >= TaskNotBackAmount)
                    {
                        ///首先使用优惠
                        i.ReceivedDiscount = PreferentialAmount + bySettlment.PreferentialAmount;
                        PreferentialAmount = 0;//优惠金额使用完
                        var YUsePrePayment = item.ActualAmount - PreferentialAmount;
                        i.UsePrePayment = YUsePrePayment + bySettlment.UsePrePayment;//剩下预收使用

                        i.ReceivedPrice = bySettlment.TaskBackAmount; //实际收款0；

                        UsePrePayment = UsePrePayment - YUsePrePayment;


                        item.UsePrePayment = TaskNotBackAmount - PreferentialAmount;
                        item.PreferentialAmount = PreferentialAmount;
                        item.TaskBackAmount = 0;
                        item.TaskNotBackAmount = 0;



                    }
                    else if (SumTaskAmountByUsePrePrice >= TaskNotBackAmount)
                    {
                        ////一次性使用优惠金额
                        i.ReceivedDiscount = bySettlment.PreferentialAmount + PreferentialAmount;
                        i.UsePrePayment = bySettlment.UsePrePayment + UsePrePayment;
                        ////实际收款金额
                        i.ReceivedPrice = (TaskNotBackAmount - PreferentialAmount - UsePrePayment) + bySettlment.TaskBackAmount;
                        item.UsePrePayment = UsePrePayment;
                        item.PreferentialAmount = PreferentialAmount;
                        item.TaskBackAmount = TaskNotBackAmount - PreferentialAmount - UsePrePayment;
                        item.TaskNotBackAmount = 0;
                        PreferentialAmount = 0;
                        UsePrePayment = 0;

                    }
                    else
                    {

                        if (SumTaskAmountByUsePrePrice > 0)
                        {
                            //本次剩余优惠
                            i.ReceivedDiscount = bySettlment.PreferentialAmount + PreferentialAmount;
                            //本次剩余预收
                            i.UsePrePayment = bySettlment.UsePrePayment + UsePrePayment;
                            //本次实际收款
                            i.ReceivedPrice = (SumTaskAmountByUsePrePrice - PreferentialAmount - UsePrePayment) + bySettlment.TaskBackAmount;
                            ////实际收款金额最后一笔
                            item.UsePrePayment = UsePrePayment;
                            //实际收款金额
                            item.TaskBackAmount = SumTaskAmountByUsePrePrice - PreferentialAmount - UsePrePayment;
                            ///总的未收金额100-
                            item.PreferentialAmount = TaskNotBackAmount - SumTaskAmountByUsePrePrice;
                            i.ReceivedDiscount += item.PreferentialAmount;
                            item.TaskNotBackAmount = i.Actualprice - i.ReceivedPrice - i.UsePrePayment - i.ReceivedDiscount;

                        }
                        else
                        {
                            ///当金额小于0的时候全部变为赠送
                            i.ReceivedDiscount = bySettlment.PreferentialAmount + item.ActualAmount;
                            i.ReceivedPrice = bySettlment.TaskBackAmount;
                            i.UsePrePayment = bySettlment.UsePrePayment;
                            item.UsePrePayment = 0;
                            item.TaskBackAmount = 0;
                            item.PreferentialAmount = item.ActualAmount;

                            ///如果金额全部小于0全部转化成优惠金额
                            model.PreferentialAmount += item.ActualAmount;
                        }
                        SumTaskAmountByUsePrePrice = 0;
                        PreferentialAmount = 0;
                        UsePrePayment = 0;
                    }
                    SumTaskAmountByUsePrePrice = SumTaskAmountByUsePrePrice - TaskNotBackAmount;
                    model.PreferentialAmount += item.PreferentialAmount;
                }
                else
                {

                    i.ReceivedDiscount = 0;
                    //本次剩余预收
                    i.UsePrePayment = 0;
                    //本次实际收款
                    i.ReceivedPrice = TaskNotBackAmount;
                    ////实际收款金额最后一笔
                    item.UsePrePayment = 0;
                    //实际收款金额
                    item.TaskBackAmount = TaskNotBackAmount;
                    ///总的未收金额100-
                    item.PreferentialAmount = 0;
                    i.ReceivedDiscount = 0;
                    item.TaskNotBackAmount = 0;
                }


                if (i.Actualprice != (i.ReceivedPrice + i.UsePrePayment + i.ReceivedDiscount))
                {
                    i.RestaurantPayStatus = RestaurantPayStatus.部分收款;
                }
                else
                {
                    i.RestaurantPayStatus = RestaurantPayStatus.已收完款;
                }


            }

            //if (SumTaskAmountByUsePrePrice > 0)
            //{

            //    await _prePaymentInfoAppService.CreateAsync(new PrePaymentInfoEnterDto
            //    {
            //        AgentPeoperUserId = AbpSession.UserId.Value,
            //        AgentPeoper = user.Name,
            //        RestaurantInfoName = model.RestaurantInfoModel.RestaurantName,
            //        RestaurantInfoId = model.RestaurantInfoModel.Id,
            //        PrePaymentPrice = SumTaskAmountByUsePrePrice,
            //        PrePaymentInfoType = PrePaymentInfoType.收预交金,
            //        PrePaymentInfoStatus = PrePaymentInfoStatus.已审核,
            //        RemarkContent = $"收款单剩余作为预收款"
            //    });
            //}

            await _repositoryReceiptInfo.UpdateAsync(model);
        }
        /// <summary>
        /// 收款单提交
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task Submit(Guid id)
        {
            var model = await _repositoryReceiptInfo.GetAsync(id);
            model.ReceiptInfoStatus = ReceiptInfoStatus.已提交;
            await _repositoryReceiptInfo.UpdateAsync(model);
        }
        /// <summary>
        /// 收款单审核
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task Examine(Guid id)
        {
            var model = await _repositoryReceiptInfo.GetAsync(id);
            model.ReceiptInfoStatus = ReceiptInfoStatus.已审核;
            await _repositoryReceiptInfo.UpdateAsync(model);
        }
        /// <summary>
        /// 收款单反审核
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task AnTiExamine(Guid id)
        {
            var model = await _repositoryReceiptInfo.GetAsync(id);
            model.ReceiptInfoStatus = ReceiptInfoStatus.退回;
            model.PaymentState = PaymentState.未缴款;
            model.UsePrePaymentSurplus = model.UsePrePaymentSurplus + model.UsePrePayment;


            model.PaymentinfoId = null;
            await _repositoryReceiptInfo.UpdateAsync(model);
        }
        /// <summary>
        /// 坏账处理
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task ToVoid(Guid id)
        {
            ///设置收款作废
            var model = await _repositoryReceiptInfo.GetAsync(id);
            if (model.PaymentinfoId.HasValue == false)
                throw new UserFriendlyException("已交款不可作废");

            model.ToVoid = ToVoidStatus.已作废;
            var list = _repositorySettlement.GetAll().Where(o => o.ReceiptInfoId == model.Id);
            ///设置收款下的收据作废
            foreach (var item in list)
            {
                item.RestaurantPayStatus = RestaurantPayStatus.作废;
                item.ReceiptInfoId = null;
            }
            await _repositoryReceiptInfo.UpdateAsync(model);
        }



        /// <summary>
        /// 获取一条收款信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ReceiptInfoDto GetById(Guid id)
        {
            var model = _repositoryReceiptInfo.GetAllIncluding(o => o.RestaurantInfoModel).Where(o => o.Id == id && o.ToVoid != ToVoidStatus.已作废).FirstOrDefault();

            if (model == null)
                throw new UserFriendlyException("该收款单已作废不可查看明细");

            //该餐厅的初始预交金
            var s = _repositoryPrePaymentInfoModel.GetAll().Where(o => o.RestaurantInfoId == model.RestaurantId && o.PrePaymentInfoStatus == PrePaymentInfoStatus.已审核 && o.PrePaymentInfoType == PrePaymentInfoType.收预交金).Sum(o => o.PrePaymentPrice) - _repositoryPrePaymentInfoModel.GetAll().Where(o => o.RestaurantInfoId == model.RestaurantId && o.PrePaymentInfoStatus == PrePaymentInfoStatus.已审核 && o.PrePaymentInfoType == PrePaymentInfoType.退预交金).Sum(o => o.PrePaymentPrice);


            //使用的预交金(不包括自己)
            var y = _repositoryReceiptInfo.GetAll().Where(o => o.RestaurantId == model.RestaurantId && o.ToVoid == ToVoidStatus.未作废 && o.Id != model.Id).Sum(o => o.UsePrePayment);

            var dto = _map.Map<ReceiptInfoDto>(model);

            dto.UsePrePaymentSurplus = s - y;
            return dto;
        }

        public async Task<IPagedList<ReceiptViewDto>> GetReceiptListAsync(int pageIdx, int pageSize)
        {
            var model = _repositoryReceiptInfo.GetAll();
            var settlement = _repositorySettlement.GetAll();
            var data = model.Join(settlement, a => a.Id, b => b.ReceiptInfoId, (a, b) => new
            {
                b.EmployeeDriverid,
                a.TaskBackAmount
            }).GroupBy(o => o.EmployeeDriverid).Select(x => new
            {
                EmployeeDriverid = x.Key,
                ReceiptPrice = x.Sum(y => y.TaskBackAmount),
                ReceiptCount = x.Count(),
            }).Join(_repositoryUser.GetAll(), a => a.EmployeeDriverid, b => b.Id, (a, b) => new ReceiptViewDto
            {
                PaymentPersonUserId = a.EmployeeDriverid.Value,
                PaymentPerson = b.Name,
                PaymentCount = a.ReceiptCount,
                PaymentPrice = a.ReceiptPrice
            });

            return await data.ToPagedListAsync(pageIdx, pageSize);
        }
        #region 后台收款单列表
        /// <summary>
        /// 收款单(分页)
        /// </summary>
        /// <returns></returns>
        public async Task<IPagedList<ReceiptInfoDto>> GetPagedListAsync(int pageIdx, int pageSize, DateTime? ReceiptBeginTime, DateTime? ReceiptEndTime, DateTime? PaymentBeginTime, DateTime? PaymentEndTime, long? AgentPeoperUserId, long? PaymentPersonUserId, string ReceiptInfoNumber, string RestaurantName, ReceiptInfoStatus? ReceiptInfoStatus)
        {
            var user = await GetCurrentUserAsync();
            var model = _repositoryReceiptInfo.GetAllIncluding(o => o.RestaurantInfoModel).Where(o => o.FactoryinfoId == user.FactoryinfoId && o.ToVoid == ToVoidStatus.未作废);




            var data = model.Join(_repositorySettlementAccount.GetAll(), a => a.CapitalAccountId, b => b.Id, (a, b) => new ReceiptInfoDto
            {
                Id = a.Id,
                FactoryinfoId = a.FactoryinfoId,
                AgentPeoperUserId = a.AgentPeoperUserId,
                AgentPeoper = a.AgentPeoper,
                Dateofreceipt = a.Dateofreceipt,
                PaymentPersonUserId = a.PaymentPersonUserId,
                PaymentPerson = a.PaymentPerson,
                DateofPayment = a.DateofPayment,
                ReceiptInfoNumber = a.ReceiptInfoNumber,
                ReceiptInfoStatus = a.ReceiptInfoStatus,
                CapitalAccountId = a.CapitalAccountId,
                AccountName = b.Name,
                AudtiTime = a.AudtiTime,
                PaymentState = a.PaymentState,
                PaymentTime = a.PaymentTime,
                PreferentialAmount = a.PreferentialAmount,
                RemarksConten = a.RemarksConten,
                RestaurantId = a.RestaurantId,
                RestaurantName = a.RestaurantInfoModel.RestaurantName,
                TaskBackAmount = a.TaskBackAmount,
                ActualAmount = a.ActualAmount,
                WholeAmount = a.WholeAmount,
                UsePrePayment = a.UsePrePayment,
                ToVoid = a.ToVoid,
                UsePrePaymentSurplus = a.UsePrePaymentSurplus
            }).GroupJoin(_repositoryReceiptInfoBySettlementModel.GetAll().Where(o => o.ToVoidStatus != ToVoidStatus.已作废).GroupBy(o => o.ReceiptInfoId).Select(s => new
            {
                ReceiptInfoId = s.Key,
                PreferentialAmount = s.Sum(sum => sum.PreferentialAmount),
                UsePrePayment = s.Sum(sum => sum.UsePrePayment),
            }), a => a.Id, b => b.ReceiptInfoId, (a, b) => new ReceiptInfoDto
            {
                Id = a.Id,
                FactoryinfoId = a.FactoryinfoId,
                AgentPeoperUserId = a.AgentPeoperUserId,
                AgentPeoper = a.AgentPeoper,
                Dateofreceipt = a.Dateofreceipt,
                PaymentPersonUserId = a.PaymentPersonUserId,
                PaymentPerson = a.PaymentPerson,
                DateofPayment = a.DateofPayment,
                ReceiptInfoNumber = a.ReceiptInfoNumber,
                ReceiptInfoStatus = a.ReceiptInfoStatus,
                CapitalAccountId = a.CapitalAccountId,
                AccountName = a.AccountName,
                AudtiTime = a.AudtiTime,
                PaymentState = a.PaymentState,
                PaymentTime = a.PaymentTime,
                RemarksConten = a.RemarksConten,
                RestaurantId = a.RestaurantId,
                RestaurantName = a.RestaurantName,
                TaskBackAmount = a.TaskBackAmount,
                ActualAmount = a.ActualAmount,
                //PreferentialAmount = b.Sum(o => o.PreferentialAmount),
                //UsePrePayment = b.Sum(o => o.UsePrePayment),
                PreferentialAmount = a.PreferentialAmount,
                UsePrePayment = a.UsePrePayment,
                WholeAmount = a.WholeAmount,
                ToVoid = a.ToVoid,
                UsePrePaymentSurplus = a.UsePrePaymentSurplus

            });
            if (ReceiptBeginTime.HasValue)
                data = data.Where(o => o.Dateofreceipt >= ReceiptBeginTime);
            if (ReceiptEndTime.HasValue)
                data = data.Where(o => o.Dateofreceipt <= ReceiptEndTime.Value.AddHours(24));

            if (PaymentBeginTime.HasValue)
                data = data.Where(o => o.DateofPayment >= PaymentBeginTime);
            if (PaymentEndTime.HasValue)
                data = data.Where(o => o.DateofPayment <= PaymentEndTime.Value.AddHours(24));

            if (AgentPeoperUserId.HasValue)
                data = data.Where(o => o.AgentPeoperUserId == AgentPeoperUserId);
            if (PaymentPersonUserId.HasValue)
                data = data.Where(o => o.PaymentPersonUserId == PaymentPersonUserId);

            if (!string.IsNullOrEmpty(ReceiptInfoNumber))
                data = data.Where(o => o.ReceiptInfoNumber == ReceiptInfoNumber);
            if (!string.IsNullOrEmpty(RestaurantName))
                data = data.Where(o => o.RestaurantName.Contains(RestaurantName));

            if (ReceiptInfoStatus.HasValue)
                data = data.Where(o => o.ReceiptInfoStatus == ReceiptInfoStatus);

            return await data.OrderByDescending(o => o.Dateofreceipt).ToPagedListAsync(pageIdx, pageSize);
        }


        public async Task<List<ReceiptInfoDto>> GetAllListAsync(DateTime? ReceiptBeginTime, DateTime? ReceiptEndTime, DateTime? PaymentBeginTime, DateTime? PaymentEndTime, long? AgentPeoperUserId, long? PaymentPersonUserId, string ReceiptInfoNumber, string RestaurantName, ReceiptInfoStatus? ReceiptInfoStatus)
        {
            var user = await GetCurrentUserAsync();
            var model = _repositoryReceiptInfo.GetAllIncluding(o => o.RestaurantInfoModel).Where(o => o.FactoryinfoId == user.FactoryinfoId && o.ToVoid == ToVoidStatus.未作废);
            var data = model.Join(_repositorySettlementAccount.GetAll(), a => a.CapitalAccountId, b => b.Id, (a, b) => new ReceiptInfoDto
            {
                Id = a.Id,
                FactoryinfoId = a.FactoryinfoId,
                AgentPeoperUserId = a.AgentPeoperUserId,
                AgentPeoper = a.AgentPeoper,
                Dateofreceipt = a.Dateofreceipt,
                PaymentPersonUserId = a.PaymentPersonUserId,
                PaymentPerson = a.PaymentPerson,
                DateofPayment = a.DateofPayment,
                ReceiptInfoNumber = a.ReceiptInfoNumber,
                ReceiptInfoStatus = a.ReceiptInfoStatus,
                CapitalAccountId = a.CapitalAccountId,
                AccountName = b.Name,
                AudtiTime = a.AudtiTime,
                PaymentState = a.PaymentState,
                PaymentTime = a.PaymentTime,
                PreferentialAmount = a.PreferentialAmount,
                RemarksConten = a.RemarksConten,
                RestaurantId = a.RestaurantId,
                RestaurantName = a.RestaurantInfoModel.RestaurantName,
                TaskBackAmount = a.TaskBackAmount,
                ActualAmount = a.ActualAmount,
                WholeAmount = a.WholeAmount,
                UsePrePayment = a.UsePrePayment,
                ToVoid = a.ToVoid,
                UsePrePaymentSurplus = a.UsePrePaymentSurplus
            }).GroupJoin(_repositoryReceiptInfoBySettlementModel.GetAll().Where(o => o.ToVoidStatus != ToVoidStatus.已作废).GroupBy(o => o.ReceiptInfoId).Select(s => new
            {
                ReceiptInfoId = s.Key,
                PreferentialAmount = s.Sum(sum => sum.PreferentialAmount),
                UsePrePayment = s.Sum(sum => sum.UsePrePayment),
            }), a => a.Id, b => b.ReceiptInfoId, (a, b) => new ReceiptInfoDto
            {
                Id = a.Id,
                FactoryinfoId = a.FactoryinfoId,
                AgentPeoperUserId = a.AgentPeoperUserId,
                AgentPeoper = a.AgentPeoper,
                Dateofreceipt = a.Dateofreceipt,
                PaymentPersonUserId = a.PaymentPersonUserId,
                PaymentPerson = a.PaymentPerson,
                DateofPayment = a.DateofPayment,
                ReceiptInfoNumber = a.ReceiptInfoNumber,
                ReceiptInfoStatus = a.ReceiptInfoStatus,
                CapitalAccountId = a.CapitalAccountId,
                AccountName = a.AccountName,
                AudtiTime = a.AudtiTime,
                PaymentState = a.PaymentState,
                PaymentTime = a.PaymentTime,
                RemarksConten = a.RemarksConten,
                RestaurantId = a.RestaurantId,
                RestaurantName = a.RestaurantName,
                TaskBackAmount = a.TaskBackAmount,
                ActualAmount = a.ActualAmount,
                //PreferentialAmount = b.Sum(o => o.PreferentialAmount),
                //UsePrePayment = b.Sum(o => o.UsePrePayment),
                PreferentialAmount = a.PreferentialAmount,
                UsePrePayment = a.UsePrePayment,
                WholeAmount = a.WholeAmount,
                ToVoid = a.ToVoid,
                UsePrePaymentSurplus = a.UsePrePaymentSurplus

            });
            if (ReceiptBeginTime.HasValue)
                data = data.Where(o => o.Dateofreceipt >= ReceiptBeginTime);
            if (ReceiptEndTime.HasValue)
                data = data.Where(o => o.Dateofreceipt <= ReceiptEndTime.Value.AddHours(24));

            if (PaymentBeginTime.HasValue)
                data = data.Where(o => o.DateofPayment >= PaymentBeginTime);
            if (PaymentEndTime.HasValue)
                data = data.Where(o => o.DateofPayment <= PaymentEndTime.Value.AddHours(24));

            if (AgentPeoperUserId.HasValue)
                data = data.Where(o => o.AgentPeoperUserId == AgentPeoperUserId);
            if (PaymentPersonUserId.HasValue)
                data = data.Where(o => o.PaymentPersonUserId == PaymentPersonUserId);

            if (!string.IsNullOrEmpty(ReceiptInfoNumber))
                data = data.Where(o => o.ReceiptInfoNumber == ReceiptInfoNumber);
            if (!string.IsNullOrEmpty(RestaurantName))
                data = data.Where(o => o.RestaurantName.Contains(RestaurantName));

            if (ReceiptInfoStatus.HasValue)
                data = data.Where(o => o.ReceiptInfoStatus == ReceiptInfoStatus);

            return await data.OrderByDescending(o => o.Dateofreceipt).ToListAsync();
        }
        #endregion
        /// <summary>
        /// 根据收款人获取收款详情
        /// </summary>
        /// <param name="AgentPeoperUserId"></param>
        /// <param name="beginTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        public async Task<List<ReceiptDetailsDto>> GetReceiptDetailsAsync(long AgentPeoperUserId, DateTime? beginTime, DateTime? endTime, ReceiptInfoStatus? ReceiptInfoStatus)
        {
            ///通过收款人id查找他的收款单信息
            var ReceiptInfoIdList = _repositorySettlement.GetAll().Where(o => o.EmployeeDriverid == AgentPeoperUserId).Join(_repositoryReceiptInfoBySettlementModel.GetAll().Where(o => o.ToVoidStatus == ToVoidStatus.未作废), i => i.Id, n => n.SettlementId, (i, n) => new
            {
                n.ReceiptInfoId
            });
            var model = _repositoryReceiptInfo.GetAllIncluding(o => o.RestaurantInfoModel).Where(o => o.ToVoid == ToVoidStatus.未作废 && ReceiptInfoIdList.Any(s => s.ReceiptInfoId == o.Id) && o.PaymentState == PaymentState.未缴款);
            var data = model.Join(_repositorySettlementAccount.GetAll(), a => a.CapitalAccountId, b => b.Id, (a, b) => new ReceiptDetailsDto
            {
                Id = a.Id,
                ReceiptInfoStatus = a.ReceiptInfoStatus,
                Dateofreceipt = a.Dateofreceipt,
                ReceiptInfoNumber = a.ReceiptInfoNumber,
                AccountName = b.Name,
                RestaurantName = a.RestaurantInfoModel.RestaurantName,
                TaskBackAmount = a.TaskBackAmount,
                PreferentialAmount = a.PreferentialAmount,
                UsePrePayment = a.UsePrePayment,
                UsePrePaymentSurplus = a.UsePrePaymentSurplus
            });

            if (beginTime.HasValue)
                data = data.Where(o => o.Dateofreceipt >= beginTime);
            if (endTime.HasValue)
                data = data.Where(o => o.Dateofreceipt <= endTime.Value.AddHours(24));

            if (ReceiptInfoStatus.HasValue)
                data = data.Where(o => o.ReceiptInfoStatus == ReceiptInfoStatus);

            return await data.OrderByDescending(o => o.Dateofreceipt).ToListAsync();
        }
        #region 后台快速收款
        /// <summary>
        /// 后台快速收款
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>

        public async Task QuickReceipt(QuickReceiptListOutput input)
        {
            var user = await base.GetCurrentUserAsync();
            foreach (var item in input.QuickReceipts)
            {

                try
                {

                    var parCountPrice = await _prePaymentInfoAppService.GetRestaurantInfoNamePrePayment(item.RestaurantId);
                    if (item.UsePrePayment > parCountPrice)
                        throw new UserFriendlyException("预付金不足");

                    if (item.ActualAmount < item.TaskBackAmount + item.UsePrePayment + item.PreferentialAmount)
                        throw new UserFriendlyException("本次收款金额合计大于应收金额");

                    var agentUser = await _repositoryUser.GetAsync(item.AgentPeoperUserId);
                    var model = item.MapTo<ReceiptInfoModel>();
                    model.Id = _guid.Create();
                    model.FactoryinfoId = user.FactoryinfoId.Value;
                    model.AgentPeoper = agentUser.Name;
                    model.Dateofreceipt = DateTime.Now;
                    model.UsePrePaymentSurplus = parCountPrice - item.UsePrePayment;

                    var m = _repositorySettlement.GetAll().Where(o => o.ExamineStatus == ExamineStatus.已审核 &&
                    o.FactoryinfoId == user.FactoryinfoId && (o.RestaurantPayStatus == RestaurantPayStatus.未收款 ||
            o.RestaurantPayStatus == RestaurantPayStatus.部分收款) && o.Restaurantid == item.RestaurantId).OrderByDescending(o => o.CreationTime);

                    ///总的应收金额
                    var sum = m.Sum(s => s.Actualprice - s.ReceivedPrice - s.UsePrePayment - s.ReceivedDiscount);
                    ///总的本次得到的金
                    var SumTaskAmountByUsePrePrice = model.TaskBackAmount + model.UsePrePayment;//总金额
                    var PreferentialAmount = model.PreferentialAmount;//优惠金额
                    var UsePrePayment = model.UsePrePayment;//预收金额///计算出所有符合当前结算的收据                                  
                    model.WholeAmount = m.Sum(o => o.Actualprice);

                    var TempMin = 0m; ///总的付的金额
                                      /// 首先计算付的得到付的总金额;
                    if (!(item.PreferentialAmount == 0m && item.TaskBackAmount == 0m && item.UsePrePayment == 0m))
                    {
                        foreach (var i in m.Where(o => o.Actualprice < 0))
                        {
                            if (PreferentialAmount < 0)
                            {
                                if (Math.Abs(PreferentialAmount) > Math.Abs(i.Actualprice))
                                {
                                    i.ReceivedPrice = 0;
                                    i.ReceivedDiscount = i.Actualprice;
                                    PreferentialAmount = PreferentialAmount - i.Actualprice;
                                }
                                else
                                {
                                    i.ReceivedPrice = i.Actualprice - PreferentialAmount;
                                    i.ReceivedDiscount = PreferentialAmount;
                                    PreferentialAmount = 0;
                                }

                            }
                            ReceiptInfoBySettlementModel receiptInfoBySettlementModel = new ReceiptInfoBySettlementModel();
                            receiptInfoBySettlementModel.Id = _guid.Create();
                            receiptInfoBySettlementModel.FactoryinfoId = user.FactoryinfoId.Value;
                            receiptInfoBySettlementModel.ReceiptInfoId = model.Id;
                            receiptInfoBySettlementModel.SettlementId = i.Id;
                            i.ReceiptInfoId = model.Id;
                            i.ReceivedDiscount = 0;
                            i.UsePrePayment = 0;

                            //使用后剩余优惠金额
                            receiptInfoBySettlementModel.ActualAmount = i.Actualprice;
                            receiptInfoBySettlementModel.UsePrePayment = 0;
                            receiptInfoBySettlementModel.PreferentialAmount = i.ReceivedDiscount;
                            receiptInfoBySettlementModel.TaskBackAmount = i.ReceivedPrice;
                            receiptInfoBySettlementModel.TaskNotBackAmount = 0;
                            TempMin += i.Actualprice;

                            if (!i.EmployeeDriverid.HasValue)
                                i.EmployeeDriverid = user.Id;

                            i.RestaurantPayStatus = RestaurantPayStatus.已收完款;
                            _repositoryReceiptInfoBySettlementModel.Insert(receiptInfoBySettlementModel);

                        }
                        ///重新的到总的可使用金额
                        SumTaskAmountByUsePrePrice = Math.Abs(TempMin) + SumTaskAmountByUsePrePrice + PreferentialAmount;
                        foreach (var i in m.Where(o => o.Actualprice > 0))
                        {
                            var bySettlment = _repositoryReceiptInfoBySettlementModel.GetAll().Where(o => o.SettlementId == i.Id && o.ToVoidStatus != ToVoidStatus.已作废).GroupBy(o => o.SettlementId).Select(o => new
                            {
                                Id = o.Key,
                                TaskNotBackAmount = o.Sum(s => s.TaskNotBackAmount),
                                TaskBackAmount = o.Sum(s => s.TaskBackAmount),
                                UsePrePayment = o.Sum(s => s.UsePrePayment),
                                PreferentialAmount = o.Sum(s => s.PreferentialAmount),
                                SumAmount = o.Sum(s => (s.PreferentialAmount + s.UsePrePayment + s.TaskBackAmount))
                            }).ToList()?.FirstOrDefault();


                            if (bySettlment == null)
                            {
                                bySettlment = new
                                {
                                    Id = Guid.NewGuid(),
                                    TaskNotBackAmount = 0.0m,
                                    TaskBackAmount = 0.0m,
                                    UsePrePayment = 0.0m,
                                    PreferentialAmount = 0.0m,
                                    SumAmount = 0.0m,
                                };
                            }

                            ReceiptInfoBySettlementModel receiptInfoBySettlementModel = new ReceiptInfoBySettlementModel();
                            receiptInfoBySettlementModel.Id = _guid.Create();
                            receiptInfoBySettlementModel.FactoryinfoId = user.FactoryinfoId.Value;
                            receiptInfoBySettlementModel.ReceiptInfoId = model.Id;
                            receiptInfoBySettlementModel.SettlementId = i.Id;
                            i.ReceiptInfoId = model.Id;
                            //总的未付款情况
                            var TaskNotBackAmount = i.Actualprice - bySettlment.SumAmount;//剩余多少钱
                            if (TaskNotBackAmount > 0)
                            {
                                if (SumTaskAmountByUsePrePrice > 0)
                                {
                                    //优惠金额如果大于应收
                                    if (PreferentialAmount >= TaskNotBackAmount)
                                    {
                                        i.ReceivedDiscount = TaskNotBackAmount + bySettlment.PreferentialAmount;
                                        i.ReceivedPrice = bySettlment.TaskBackAmount;
                                        i.UsePrePayment = bySettlment.UsePrePayment;
                                        //使用后剩余优惠金额
                                        PreferentialAmount = PreferentialAmount - TaskNotBackAmount;

                                        receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                        receiptInfoBySettlementModel.UsePrePayment = 0;
                                        receiptInfoBySettlementModel.PreferentialAmount = TaskNotBackAmount;
                                        receiptInfoBySettlementModel.TaskBackAmount = 0;
                                        receiptInfoBySettlementModel.TaskNotBackAmount = 0;


                                    }
                                    else if (UsePrePayment >= TaskNotBackAmount)
                                    {
                                        ///一次性使用预收金额
                                        i.UsePrePayment = TaskNotBackAmount + bySettlment.UsePrePayment;
                                        i.ReceivedDiscount = bySettlment.PreferentialAmount;
                                        i.ReceivedPrice = bySettlment.TaskBackAmount;

                                        UsePrePayment = UsePrePayment - TaskNotBackAmount;

                                        receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                        receiptInfoBySettlementModel.UsePrePayment = TaskNotBackAmount;
                                        receiptInfoBySettlementModel.PreferentialAmount = 0;
                                        receiptInfoBySettlementModel.TaskBackAmount = 0;
                                        receiptInfoBySettlementModel.TaskNotBackAmount = 0;

                                    }
                                    else if (UsePrePayment + PreferentialAmount >= TaskNotBackAmount)
                                    {
                                        ///首先使用优惠
                                        i.ReceivedDiscount = PreferentialAmount + bySettlment.PreferentialAmount;
                                        PreferentialAmount = 0;//优惠金额使用完
                                        var YUsePrePayment = TaskNotBackAmount - PreferentialAmount;
                                        i.UsePrePayment = YUsePrePayment + bySettlment.UsePrePayment;//剩下预收使用

                                        i.ReceivedPrice = bySettlment.TaskBackAmount; //实际收款0；

                                        UsePrePayment = UsePrePayment - YUsePrePayment;

                                        receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                        receiptInfoBySettlementModel.UsePrePayment = TaskNotBackAmount - PreferentialAmount;
                                        receiptInfoBySettlementModel.PreferentialAmount = PreferentialAmount;
                                        receiptInfoBySettlementModel.TaskBackAmount = 0;
                                        receiptInfoBySettlementModel.TaskNotBackAmount = 0;



                                    }
                                    else if (SumTaskAmountByUsePrePrice >= TaskNotBackAmount)
                                    {
                                        ////一次性使用优惠金额
                                        i.ReceivedDiscount = bySettlment.PreferentialAmount + PreferentialAmount;
                                        i.UsePrePayment = bySettlment.UsePrePayment + UsePrePayment;
                                        ////实际收款金额
                                        i.ReceivedPrice = (TaskNotBackAmount - PreferentialAmount - UsePrePayment) + bySettlment.TaskBackAmount;

                                        receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                        receiptInfoBySettlementModel.UsePrePayment = UsePrePayment;
                                        receiptInfoBySettlementModel.PreferentialAmount = PreferentialAmount;
                                        receiptInfoBySettlementModel.TaskBackAmount = TaskNotBackAmount - PreferentialAmount - UsePrePayment; ;
                                        receiptInfoBySettlementModel.TaskNotBackAmount = 0;
                                        PreferentialAmount = 0;
                                        UsePrePayment = 0;

                                    }
                                    else
                                    {
                                        ////一次性使用优惠金额
                                        i.ReceivedDiscount = bySettlment.PreferentialAmount + PreferentialAmount;
                                        i.UsePrePayment = bySettlment.UsePrePayment + UsePrePayment;
                                        ////实际收款金额最后一笔
                                        i.ReceivedPrice = (SumTaskAmountByUsePrePrice - PreferentialAmount - UsePrePayment) + bySettlment.TaskBackAmount;

                                        receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                        receiptInfoBySettlementModel.UsePrePayment = UsePrePayment;
                                        receiptInfoBySettlementModel.PreferentialAmount = PreferentialAmount;
                                        receiptInfoBySettlementModel.TaskBackAmount = SumTaskAmountByUsePrePrice - PreferentialAmount - UsePrePayment;
                                        receiptInfoBySettlementModel.TaskNotBackAmount = i.Actualprice - i.ReceivedPrice - i.UsePrePayment - i.ReceivedDiscount;
                                        SumTaskAmountByUsePrePrice = 0;
                                        PreferentialAmount = 0;
                                        UsePrePayment = 0;
                                    }
                                    if (!i.EmployeeDriverid.HasValue)
                                        i.EmployeeDriverid = item.AgentPeoperUserId;
                                    SumTaskAmountByUsePrePrice = SumTaskAmountByUsePrePrice - i.Actualprice;
                                    _repositoryReceiptInfoBySettlementModel.Insert(receiptInfoBySettlementModel);
                                }
                            }
                            else
                            {
                                continue;
                            }
                            //判断收款是否完成
                            if (i.Actualprice != (i.ReceivedPrice + i.UsePrePayment + i.ReceivedDiscount))
                            {
                                i.RestaurantPayStatus = RestaurantPayStatus.部分收款;
                            }
                            else
                            {
                                i.RestaurantPayStatus = RestaurantPayStatus.已收完款;
                            }

                        }
                    }

                    model.RemarksConten = $"快速收款{model.TaskBackAmount + model.UsePrePayment + model.PreferentialAmount}=实际收款+预收金额+优惠金额";
                    model.ReceiptInfoStatus = ReceiptInfoStatus.已提交;
                    if (m.Count() > 0)
                        await _repositoryReceiptInfo.InsertAndGetIdAsync(model);

                }
                catch (Exception exe)
                {
                    throw new UserFriendlyException("快速收款失败", exe);
                }
            }
        }
        #endregion

        #region 后台操作
        public async Task<Guid> Create_Management(ReceiptInfoEnterDto input)
        {
            Guid id = new Guid();
            if (input.Settlements != null)
            {
                var user = await base.GetCurrentUserAsync();
                ReceiptInfoModel model = new ReceiptInfoModel()
                {
                    Id = _guid.Create(),
                    FactoryinfoId = user.FactoryinfoId.Value,
                    AgentPeoper = input.AgentPeoper,
                    AgentPeoperUserId = input.AgentPeoperUserId,
                    Dateofreceipt = input.Dateofreceipt,
                    RestaurantId = input.RestaurantId,
                    CapitalAccountId = input.CapitalAccountId,
                    TaskBackAmount = input.TaskBackAmount,
                    ReceiptInfoStatus = input.ReceiptInfoStatus,
                    RemarksConten = input.RemarksConten,

                };
                //得到原始预售金
                var oldUsePrePayment = input.UsePrePaymentSurplus + input.UsePrePayment;
                //本次收款单应收总金额
                model.ActualAmount = input.Settlements.Sum(o => o.uncollected); ;
                ///实际收回金额
                //model.TaskBackAmount = input.Settlements.Sum(o => o.receipt);
                //本次使用预付款金额
                var prePayment = input.UsePrePayment;
                foreach (var item in input.Settlements)
                {
                    //查询出所有收据
                    var settlements = _repositorySettlement.GetAll().Where(o => o.Id == item.SettlementId).FirstOrDefault();

                    if (settlements != null)
                    {
                        model.WholeAmount = settlements.Actualprice;
                        ReceiptInfoBySettlementModel receiptInfoBySettlementModel = new ReceiptInfoBySettlementModel();
                        receiptInfoBySettlementModel.Id = _guid.Create();
                        receiptInfoBySettlementModel.FactoryinfoId = user.FactoryinfoId.Value;
                        receiptInfoBySettlementModel.ReceiptInfoId = model.Id;
                        receiptInfoBySettlementModel.SettlementId = item.SettlementId;
                        receiptInfoBySettlementModel.ActualAmount = item.uncollected;
                        settlements.ReceiptInfoId= model.Id;
                        //如果存在预售金优先计算本身金额是否持平
                        if (prePayment > 0)//本次预付款是否使用
                        {
                            //如果未收金额=实际收款+优惠收款直接填平
                            if (item.receipt + item.offer == item.uncollected)
                            {
                                settlements.ReceivedDiscount += item.offer;
                                settlements.ReceivedPrice += item.receipt;
                                receiptInfoBySettlementModel.PreferentialAmount = item.offer;
                                receiptInfoBySettlementModel.UsePrePayment = 0m;
                                receiptInfoBySettlementModel.TaskBackAmount = item.receipt;
                            }
                            else
                            {
                                //获取收据未付金额(前端自动填平---未付减去优惠)
                                var unprePayment = item.uncollected - item.receipt + item.offer;
                                //减去使用预付款金额是否还大于不够的金额
                                if (prePayment > unprePayment)//大于等于0预付款已使用完
                                {
                                    //收据使用的预收金
                                    settlements.UsePrePayment += unprePayment;
                                    settlements.ReceivedDiscount += item.offer;
                                    settlements.ReceivedPrice += item.receipt;
                                    receiptInfoBySettlementModel.UsePrePayment = unprePayment;
                                    receiptInfoBySettlementModel.TaskBackAmount = item.receipt;
                                    receiptInfoBySettlementModel.PreferentialAmount = item.offer;
                                    //剩余预收款
                                    prePayment = prePayment - unprePayment;

                                    model.UsePrePayment += unprePayment;


                                }
                                else//小于0继续分摊到下个收据
                                {
                                    //收据使用的预收金等于剩余的全部未付金额;
                                    settlements.UsePrePayment += prePayment;
                                    settlements.ReceivedDiscount += item.offer;
                                    settlements.ReceivedPrice += item.receipt;
                                    receiptInfoBySettlementModel.UsePrePayment = prePayment;
                                    receiptInfoBySettlementModel.TaskBackAmount = item.receipt;
                                    receiptInfoBySettlementModel.PreferentialAmount = item.offer;
                                    //预售金使用
                                    model.UsePrePayment += unprePayment;
                                    //说明预售金使用完了
                                    prePayment = 0m;

                                }

                            }

                        }
                        else
                        {
                            //本次支付金额不存在使用预收款直接添加数据
                            settlements.ReceivedPrice += item.receipt;
                            settlements.ReceivedDiscount += item.offer;
                            receiptInfoBySettlementModel.UsePrePayment = 0m;
                            receiptInfoBySettlementModel.TaskBackAmount = item.receipt;
                            receiptInfoBySettlementModel.PreferentialAmount = item.offer;

                        }

                        model.UsePrePaymentSurplus = oldUsePrePayment - model.UsePrePayment;
                        //计算实际未收回金额
                        receiptInfoBySettlementModel.TaskNotBackAmount = item.uncollected - receiptInfoBySettlementModel.PreferentialAmount - receiptInfoBySettlementModel.TaskBackAmount - receiptInfoBySettlementModel.UsePrePayment;
                        receiptInfoBySettlementModel.ToVoidStatus = ToVoidStatus.未作废;

                        ///如果优惠金额+预收款金额+实际收回金额=应收金额表示收款完成。
                        if (receiptInfoBySettlementModel.ActualAmount == (receiptInfoBySettlementModel.UsePrePayment + receiptInfoBySettlementModel.TaskBackAmount + receiptInfoBySettlementModel.PreferentialAmount))
                        {
                            var m = _repositoryReceiptInfoBySettlementModel.GetAll().Where(o => o.SettlementId == settlements.Id && o.ToVoidStatus == ToVoidStatus.未作废).Sum(s => s.UsePrePayment + s.PreferentialAmount + s.TaskBackAmount) + receiptInfoBySettlementModel.UsePrePayment + receiptInfoBySettlementModel.TaskBackAmount + receiptInfoBySettlementModel.PreferentialAmount;
                            if (m == settlements.Actualprice)
                                settlements.RestaurantPayStatus = RestaurantPayStatus.已收完款;
                            else
                                settlements.RestaurantPayStatus = RestaurantPayStatus.部分收款;
                        }


                        //备注
                        settlements.RemarksConten = item.Remarks;

                        if (!settlements.EmployeeDriverid.HasValue)//收款经办人
                            settlements.EmployeeDriverid = input.AgentPeoperUserId;

                        await _repositorySettlement.UpdateAsync(settlements);
                        await _repositoryReceiptInfoBySettlementModel.InsertAsync(receiptInfoBySettlementModel);
                    }
                }
                id = await _repositoryReceiptInfo.InsertAndGetIdAsync(model);
            }
            else
            {
                throw new UserFriendlyException(2, "请选择收据");
            }

            return id;
        }


        #endregion

        #region App司机收款
        /// <summary>
        /// App司机收款
        /// </summary>
        /// <param name="infoDto"></param>
        /// <returns></returns>
        public async Task CreateReceipt(ReceiptInfoInputEdit infoDto)
        {

            var user = await base.GetCurrentUserAsync();
            var guid = _guid.Create();
            var model = infoDto.MapTo<ReceiptInfoModel>();
            var parCountPrice = await _prePaymentInfoAppService.GetRestaurantInfoNamePrePayment(model.RestaurantId);
            if (infoDto.UsePrePayment > parCountPrice)
                throw new UserFriendlyException("预付金不足");


            var account = _repositorySettlementAccount.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId).FirstOrDefault();
            if (account == null)
                throw new UserFriendlyException("未发现系统收款账户");

            var sModel = _repositorySettlement.Get(infoDto.SettlementId);
            if (sModel.RestaurantPayStatus == RestaurantPayStatus.已收完款)
                throw new UserFriendlyException("已收款");
            //如果应收金额小0
            if (sModel.Actualprice < 0)
            {
                model.TaskBackAmount = sModel.Actualprice;
                model.UsePrePayment = 0;
                model.PreferentialAmount = 0;
            }
            else
            {

                if (infoDto.PreferentialAmount > model.ActualAmount)
                    throw new UserFriendlyException("优惠金额大于实际收款金额");
            }
            model.CapitalAccountId = account.Id;
            model.AgentPeoper = user.Name;
            model.AgentPeoperUserId = AbpSession.UserId.Value;
            model.Dateofreceipt = DateTime.Now;
            model.FactoryinfoId = user.FactoryinfoId.Value;
            model.Id = guid;
            model.UsePrePaymentSurplus = parCountPrice - model.UsePrePayment;
            model.PreferentialAmount = model.ActualAmount - model.TaskBackAmount - model.UsePrePayment;//正常情况下优惠等于 应收-实际-预收=0、
            model.WholeAmount = sModel.Actualprice;

            sModel.ReceiptInfoId = model.Id;
            sModel.ReceivedDiscount = model.PreferentialAmount;
            sModel.ReceivedPrice = model.TaskBackAmount;//实际收款+预付金额
            sModel.RestaurantPayStatus = RestaurantPayStatus.已收完款;
            sModel.UsePrePayment = model.UsePrePayment;


            ReceiptInfoBySettlementModel receiptInfoBySettlementModel = new ReceiptInfoBySettlementModel();
            receiptInfoBySettlementModel.Id = _guid.Create();
            receiptInfoBySettlementModel.FactoryinfoId = user.FactoryinfoId.Value;
            receiptInfoBySettlementModel.ReceiptInfoId = model.Id;
            receiptInfoBySettlementModel.SettlementId = infoDto.SettlementId;

            receiptInfoBySettlementModel.ActualAmount = infoDto.ActualAmount;
            receiptInfoBySettlementModel.UsePrePayment = infoDto.UsePrePayment;
            receiptInfoBySettlementModel.PreferentialAmount = infoDto.PreferentialAmount;
            receiptInfoBySettlementModel.TaskBackAmount = infoDto.TaskBackAmount;
            receiptInfoBySettlementModel.TaskNotBackAmount = infoDto.ActualAmount - (infoDto.UsePrePayment + infoDto.PreferentialAmount + infoDto.TaskBackAmount);

            await _repositoryReceiptInfoBySettlementModel.InsertAndGetIdAsync(receiptInfoBySettlementModel);
            await _repositoryReceiptInfo.InsertAndGetIdAsync(model);
        }
        #endregion
        #region App分配给司机端快速收款
        /// <summary>
        /// App分配给司机端快速收款
        /// </summary>
        /// <param name="infoDto"></param>
        /// <returns></returns>
        public async Task CreateQuickReceipt(ReceiptInfoInputQuickEdit infoDto)
        {

            var user = await base.GetCurrentUserAsync();
            var guid = _guid.Create();
            var model = infoDto.MapTo<ReceiptInfoModel>();
            try
            {
                var parCountPrice = await _prePaymentInfoAppService.GetRestaurantInfoNamePrePayment(model.RestaurantId);
                if (infoDto.UsePrePayment > parCountPrice)
                    throw new UserFriendlyException("预付金不足");

                var account = _repositorySettlementAccount.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId).FirstOrDefault();
                if (account == null)
                    throw new UserFriendlyException("未发现系统收款账户");


                model.CapitalAccountId = account.Id;
                model.AgentPeoper = user.Name;
                model.AgentPeoperUserId = AbpSession.UserId.Value;
                model.Dateofreceipt = DateTime.Now;
                model.FactoryinfoId = user.FactoryinfoId.Value;
                model.Id = guid;
                model.UsePrePaymentSurplus = parCountPrice - model.UsePrePayment;
                // model.PreferentialAmount = model.TaskBackAmount - model.UsePrePaymentSurplus;//正常情况下优惠等于 应收-实际-预收=0、
                var m = _repositorySettlement.GetAll().Where(o => o.EmployeeDriverid == user.Id && o.ExamineStatus == ExamineStatus.已审核 && (o.RestaurantPayStatus == RestaurantPayStatus.未收款 ||
                o.RestaurantPayStatus == RestaurantPayStatus.部分收款) && o.FactoryinfoId == user.FactoryinfoId && (o.Actualprice - o.UsePrePayment - o.ReceivedDiscount) > o.ReceivedPrice
                        && o.Restaurantid == infoDto.RestaurantId).OrderByDescending(o => o.CreationTime);
                var SumTaskAmountByUsePrePrice = model.TaskBackAmount + model.UsePrePayment + model.PreferentialAmount;//总金额
                var PreferentialAmount = model.PreferentialAmount;//优惠金额
                var UsePrePayment = model.UsePrePayment;//预收金额    
                var UsePrePaymentSumPrice = model.TaskBackAmount;
                model.WholeAmount = m.Sum(o => o.Actualprice);
                var TempMin = 0m; ///总的付的金额
                                  /// 首先计算付的得到付的总金额;
                if (!(infoDto.PreferentialAmount == 0m && infoDto.TaskBackAmount == 0m && infoDto.UsePrePayment == 0m))
                {
                    foreach (var i in m.Where(o => o.Actualprice < 0))
                    {
                        if (PreferentialAmount < 0)
                        {
                            if (Math.Abs(PreferentialAmount) > Math.Abs(i.Actualprice))
                            {
                                i.ReceivedPrice = 0;
                                i.ReceivedDiscount = i.Actualprice;
                                PreferentialAmount = PreferentialAmount - i.Actualprice;
                            }
                            else
                            {
                                i.ReceivedPrice = i.Actualprice - PreferentialAmount;
                                i.ReceivedDiscount = PreferentialAmount;
                                PreferentialAmount = 0;
                            }

                        }
                        ReceiptInfoBySettlementModel receiptInfoBySettlementModel = new ReceiptInfoBySettlementModel();
                        receiptInfoBySettlementModel.Id = _guid.Create();
                        receiptInfoBySettlementModel.FactoryinfoId = user.FactoryinfoId.Value;
                        receiptInfoBySettlementModel.ReceiptInfoId = model.Id;
                        receiptInfoBySettlementModel.SettlementId = i.Id;
                        i.ReceiptInfoId = model.Id;
                        i.ReceivedDiscount = 0;
                        i.UsePrePayment = 0;

                        //使用后剩余优惠金额
                        receiptInfoBySettlementModel.ActualAmount = i.Actualprice;
                        receiptInfoBySettlementModel.UsePrePayment = 0;
                        receiptInfoBySettlementModel.PreferentialAmount = i.ReceivedDiscount;
                        receiptInfoBySettlementModel.TaskBackAmount = i.ReceivedPrice;
                        receiptInfoBySettlementModel.TaskNotBackAmount = 0;
                        TempMin += i.Actualprice;

                        if (!i.EmployeeDriverid.HasValue)
                            i.EmployeeDriverid = user.Id;

                        _repositoryReceiptInfoBySettlementModel.Insert(receiptInfoBySettlementModel);

                    }
                    ///重新的到总的可使用金额
                    SumTaskAmountByUsePrePrice = Math.Abs(TempMin) + SumTaskAmountByUsePrePrice + PreferentialAmount;
                    foreach (var i in m.Where(o => o.Actualprice > 0))
                    {
                        var bySettlment = _repositoryReceiptInfoBySettlementModel.GetAll().Where(o => o.SettlementId == i.Id && o.ToVoidStatus != ToVoidStatus.已作废).GroupBy(o => o.SettlementId).Select(o => new
                        {
                            Id = o.Key,
                            TaskNotBackAmount = o.Sum(s => s.TaskNotBackAmount),
                            TaskBackAmount = o.Sum(s => s.TaskBackAmount),
                            UsePrePayment = o.Sum(s => s.UsePrePayment),
                            PreferentialAmount = o.Sum(s => s.PreferentialAmount),
                            SumAmount = o.Sum(s => (s.PreferentialAmount + s.UsePrePayment + s.TaskBackAmount))
                        }).ToList()?.FirstOrDefault();


                        if (bySettlment == null)
                        {
                            bySettlment = new
                            {
                                Id = Guid.NewGuid(),
                                TaskNotBackAmount = 0.0m,
                                TaskBackAmount = 0.0m,
                                UsePrePayment = 0.0m,
                                PreferentialAmount = 0.0m,
                                SumAmount = 0.0m,
                            };
                        }

                        ReceiptInfoBySettlementModel receiptInfoBySettlementModel = new ReceiptInfoBySettlementModel();
                        receiptInfoBySettlementModel.Id = _guid.Create();
                        receiptInfoBySettlementModel.FactoryinfoId = user.FactoryinfoId.Value;
                        receiptInfoBySettlementModel.ReceiptInfoId = model.Id;
                        receiptInfoBySettlementModel.SettlementId = i.Id;
                        i.ReceiptInfoId = model.Id;
                        //总的未付款情况
                        var TaskNotBackAmount = i.Actualprice - bySettlment.SumAmount;//剩余多少钱
                        if (TaskNotBackAmount > 0)
                        {
                            if (SumTaskAmountByUsePrePrice > 0)
                            {
                                //优惠金额如果大于应收
                                if (PreferentialAmount >= TaskNotBackAmount)
                                {
                                    i.ReceivedDiscount = TaskNotBackAmount + bySettlment.PreferentialAmount;
                                    i.ReceivedPrice = bySettlment.TaskBackAmount;
                                    i.UsePrePayment = bySettlment.UsePrePayment;
                                    //使用后剩余优惠金额
                                    PreferentialAmount = PreferentialAmount - TaskNotBackAmount;

                                    receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                    receiptInfoBySettlementModel.UsePrePayment = 0;
                                    receiptInfoBySettlementModel.PreferentialAmount = TaskNotBackAmount;
                                    receiptInfoBySettlementModel.TaskBackAmount = 0;
                                    receiptInfoBySettlementModel.TaskNotBackAmount = 0;


                                }
                                else if (UsePrePayment >= TaskNotBackAmount)
                                {
                                    ///一次性使用预收金额
                                    i.UsePrePayment = TaskNotBackAmount + bySettlment.UsePrePayment;
                                    i.ReceivedDiscount = bySettlment.PreferentialAmount;
                                    i.ReceivedPrice = bySettlment.TaskBackAmount;

                                    UsePrePayment = UsePrePayment - TaskNotBackAmount;

                                    receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                    receiptInfoBySettlementModel.UsePrePayment = TaskNotBackAmount;
                                    receiptInfoBySettlementModel.PreferentialAmount = 0;
                                    receiptInfoBySettlementModel.TaskBackAmount = 0;
                                    receiptInfoBySettlementModel.TaskNotBackAmount = 0;

                                }
                                else if (UsePrePayment + PreferentialAmount >= TaskNotBackAmount)
                                {
                                    ///首先使用优惠
                                    i.ReceivedDiscount = PreferentialAmount + bySettlment.PreferentialAmount;
                                    PreferentialAmount = 0;//优惠金额使用完
                                    var YUsePrePayment = TaskNotBackAmount - PreferentialAmount;
                                    i.UsePrePayment = YUsePrePayment + bySettlment.UsePrePayment;//剩下预收使用

                                    i.ReceivedPrice = bySettlment.TaskBackAmount; //实际收款0；

                                    UsePrePayment = UsePrePayment - YUsePrePayment;

                                    receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                    receiptInfoBySettlementModel.UsePrePayment = TaskNotBackAmount - PreferentialAmount;
                                    receiptInfoBySettlementModel.PreferentialAmount = PreferentialAmount;
                                    receiptInfoBySettlementModel.TaskBackAmount = 0;
                                    receiptInfoBySettlementModel.TaskNotBackAmount = 0;



                                }
                                else if (SumTaskAmountByUsePrePrice >= TaskNotBackAmount)
                                {
                                    ////一次性使用优惠金额
                                    i.ReceivedDiscount = bySettlment.PreferentialAmount + PreferentialAmount;
                                    i.UsePrePayment = bySettlment.UsePrePayment + UsePrePayment;
                                    ////实际收款金额
                                    i.ReceivedPrice = (TaskNotBackAmount - PreferentialAmount - UsePrePayment) + bySettlment.TaskBackAmount;

                                    receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                    receiptInfoBySettlementModel.UsePrePayment = UsePrePayment;
                                    receiptInfoBySettlementModel.PreferentialAmount = PreferentialAmount;
                                    receiptInfoBySettlementModel.TaskBackAmount = TaskNotBackAmount - PreferentialAmount - UsePrePayment; ;
                                    receiptInfoBySettlementModel.TaskNotBackAmount = 0;
                                    PreferentialAmount = 0;
                                    UsePrePayment = 0;

                                }
                                else
                                {
                                    ////一次性使用优惠金额
                                    i.ReceivedDiscount = bySettlment.PreferentialAmount + PreferentialAmount;
                                    i.UsePrePayment = bySettlment.UsePrePayment + UsePrePayment;
                                    ////实际收款金额最后一笔
                                    i.ReceivedPrice = (SumTaskAmountByUsePrePrice - PreferentialAmount - UsePrePayment) + bySettlment.TaskBackAmount;

                                    receiptInfoBySettlementModel.ActualAmount = TaskNotBackAmount;
                                    receiptInfoBySettlementModel.UsePrePayment = UsePrePayment;
                                    receiptInfoBySettlementModel.PreferentialAmount = PreferentialAmount;
                                    receiptInfoBySettlementModel.TaskBackAmount = SumTaskAmountByUsePrePrice - PreferentialAmount - UsePrePayment;
                                    receiptInfoBySettlementModel.TaskNotBackAmount = i.Actualprice - i.ReceivedPrice - i.UsePrePayment - i.ReceivedDiscount;
                                    SumTaskAmountByUsePrePrice = 0;
                                    PreferentialAmount = 0;
                                    UsePrePayment = 0;
                                }
                                if (!i.EmployeeDriverid.HasValue)
                                    i.EmployeeDriverid = user.Id;
                                SumTaskAmountByUsePrePrice = SumTaskAmountByUsePrePrice - i.Actualprice;
                                _repositoryReceiptInfoBySettlementModel.Insert(receiptInfoBySettlementModel);
                            }
                        }
                        else
                        {
                            continue;
                        }
                        //判断收款是否完成
                        if (i.Actualprice != (i.ReceivedPrice + i.UsePrePayment + i.ReceivedDiscount))
                        {
                            i.RestaurantPayStatus = RestaurantPayStatus.部分收款;
                        }
                        else
                        {
                            i.RestaurantPayStatus = RestaurantPayStatus.已收完款;
                        }

                    }
                }

                if (m.Count() > 0)
                    await _repositoryReceiptInfo.InsertAndGetIdAsync(model);

            }
            catch (Exception exe)
            {

                throw new UserFriendlyException("快速收款失败", exe);
            }
        }
        #endregion

    }
}
